<?php
/**
 * Created by kongy@mysoft.com.cn.
 * Date: 2016/1/28
 * Time: 14:53
 */

namespace common\services\common;

use linslin\yii2\curl\Curl;

class Request
{
    protected $curl;

    public function __construct()
    {
        $this->curl = new Curl();
    }

    /**
     * @param string $api
     * @param array $params
     * @param string $method GET or POST
     * @param bool $async
     * @return array|false
     */
    public function request($api, $params = [], $method = 'GET', $async = false)
    {
        if (!is_array($params)) {
            throw new \InvalidArgumentException('$params 参数必须是数组!');
        }

        //生成签名
//        $sign = $this->createSigin($tenantCode, $params, $action);
//        $params = ['handler' => $action, 'sign' => $sign, 'data' => json_encode($params, JSON_UNESCAPED_UNICODE)];
        $params['access_token'] = $this->getAccessToken();
        $params_encode = json_encode($params, JSON_UNESCAPED_UNICODE);

        try {
            if ($method == 'GET') {
                $result = $this->get($api, $params);
            } elseif ($method == 'POST') {
                $result = $this->post($api, $params, $async);
            } else {
                $result = ['errcode' => -1, 'errmsg' => '调用多租户接口失败:无效的请求'];
            }

        } catch (\Exception $ex) {
            \Yii::error($ex);
            $result = ['errcode' => -1, 'errmsg' => '调用多租户接口失败:' . $ex->getMessage()];
        }

        return $result;
    }

    /**
     * @param $url
     * @param $params
     * @return mixed
     * @throws \Exception
     */
    private function get($url, $params)
    {
        if (strpos($url, '?') !== false) {
            $url .= '&' . http_build_query($params);
        } else {
            $url .= '?' . http_build_query($params);
        }

        return $this->curl->get($url);
    }

    /**
     * @param string $url
     * @param array $params
     * @param bool $async 是否异步
     * @return mixed
     */
    private function post($url, $params, $async)
    {
        if ($async) {
            $this->postAsync($url, $params);
            return ['errcode' => 0, 'errmsg' => ''];
        } else {
            return $this->curl->setOption(CURLOPT_POSTFIELDS, http_build_query($params))->post($url);
        }
    }

    private function getAccessToken()
    {
        $url = \Yii::$app->params['passport_api_url'];
        $client_id = \Yii::$app->params['client_id'];
        $client_secret = \Yii::$app->params['client_secret'];

        $param = [
            'grant_type' => 'client_credentials',
            'client_secret' => $client_secret,
            'client_id' => $client_id
        ];

        $response = $this->curl->setOption(CURLOPT_POSTFIELDS, http_build_query($param))->post($url);
        $result = json_decode($response);
        \Yii::trace('getToken: ' . $url . 'params: ' . json_encode($param));
        if (isset($result->access_token)) {
            return $result->access_token;
        } else {
            throw new \Exception('获取token失败!' . $response);
        }
    }

    private function postAsync($url, $params, $port = 80)
    {
        $post_string = http_build_query($params);
        $parts = parse_url($url);
        $fp = fsockopen($parts['host'],
            isset($parts['port']) ? $parts['port'] : $port,
            $errno, $errstr, 30);

        $out = "POST " . $parts['path'] . (isset($parts['query']) ? ('?' . $parts['query']) : '') . " HTTP/1.1\r\n";
        $out .= "Host: " . $parts['host'] . "\r\n";
        $out .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $out .= "Content-Length: " . strlen($post_string) . "\r\n";
        $out .= "Connection: Close\r\n\r\n";
        if (isset($post_string)) $out .= $post_string;

        fwrite($fp, $out);
        fclose($fp);
    }
}